import json
import os
import random

from pptx import Presentation

from func.generate_section import generate_section_content
from utils.log import logger
from utils.logger import LOG
from utils.outline_parser import  chapter2md, chapter2json, outline_to_json
from utils.template_manager import load_template, print_layouts, get_layout_mapping
from utils.utils import remove_all_slides
from config.output_file_config import output_dir, template_dir
from config.example import reference

def format_text(paragraph, text):
    """
    格式化文本，处理加粗内容。假设 ** 包围的文本表示需要加粗。
    """
    while '**' in text:
        start = text.find('**')
        end = text.find('**', start + 2)

        if start != -1 and end != -1:
            # 添加加粗之前的普通文本
            if start > 0:
                run = paragraph.add_run()
                run.text = text[:start]

            # 添加加粗文本
            bold_run = paragraph.add_run()
            bold_run.text = text[start + 2:end]
            bold_run.font.bold = True  # 设置加粗

            # 处理剩余文本
            text = text[end + 2:]
        else:
            break

    # 添加剩余的普通文本
    if text:
        run = paragraph.add_run()
        run.text = text


# 生成 PowerPoint 演示文稿
def generate_presentation(powerpoint_data, template_id: int, text: str, name: str):
    """
    :param powerpoint_data: outline,大纲内容,此时是
    :param template_color_id: 模板主题色ID
    :param name: 生成的PPT名称
    :return: 生成成功
    """

    # 找寻模板主题色
    template_path = os.path.join(template_dir, f'{template_id}.pptx')

    # 检查模板文件是否存在
    if not os.path.exists(template_path):
        logger.error(f"模板文件 '{template_path}' 不存在。")  # 记录错误日志
        raise FileNotFoundError(f"模板文件 '{template_path}' 不存在。")

    prs = Presentation(template_path)  # 加载 PowerPoint 模板
    remove_all_slides(prs)  # 清除模板中的所有幻灯片

    # 将outline大纲内容转换为json
    powerpoint_data = json.loads(outline_to_json(powerpoint_data))  # 大纲转为json后，按章节生成小节内容

    prs.core_properties.title = powerpoint_data.title  # 设置 PowerPoint 的核心标题

    # 遍历所有幻灯片数据，生成对应的 PowerPoint 幻灯片
    for slide in powerpoint_data.slides:
        # 确保布局索引不超出范围，超出则使用默认布局
        if slide.layout_id >= len(prs.slide_layouts):
            slide_layout = prs.slide_layouts[0]
        else:
            slide_layout = prs.slide_layouts[slide.layout_id]

        new_slide = prs.slides.add_slide(slide_layout)  # 添加新的幻灯片

        # 设置幻灯片标题
        if new_slide.shapes.title:
            new_slide.shapes.title.text = slide.content.title
            LOG.debug(f"设置幻灯片标题: {slide.content.title}")

        # 添加文本内容
        for shape in new_slide.shapes:
            # 只处理非标题的文本框
            if shape.has_text_frame and not shape == new_slide.shapes.title:
                text_frame = shape.text_frame
                text_frame.clear()  # 清除原有内容
                # 将要点内容作为项目符号列表添加到文本框中
                for point in slide.content.bullet_points:
                    p = text_frame.add_paragraph()
                    p.level = point["level"]  # 设置项目符号的级别
                    format_text(p, point["text"])  # 调用 format_text 方法来处理加粗文本
                    LOG.debug(f"添加列表项: {p.text}，级别: {p.level}")
                break

        # 插入图片
        if slide.content.image_path:
            image_full_path = os.path.join(os.getcwd(), slide.content.image_path)  # 构建图片的绝对路径
            if os.path.exists(image_full_path):
                # 插入图片到占位符中
                for shape in new_slide.placeholders:
                    if shape.placeholder_format.type == 18:  # 18 表示图片占位符
                        shape.insert_picture(image_full_path)
                        LOG.debug(f"插入图片: {image_full_path}")
                        break
            else:
                LOG.warning(f"图片路径 '{image_full_path}' 不存在，跳过此图片。")

    # 保存生成的 PowerPoint 文件
    name = name + ".pptx"
    # 保存的文件路径
    output_file = os.path.join(output_dir, name)
    prs.save(output_file)
    LOG.info(f"演示文稿已保存到 '{output_file}'")


def copy_placeholder_text_to_slide(slide_layout, new_slide):
    """
    复制母版中的占位符文本到新幻灯片
    :param slide_layout: 布局对象（母版布局）
    :param new_slide: 新的幻灯片对象
    """
    for shape in slide_layout.shapes:
        if shape.has_text_frame:
            print("母版文本: ", shape.text_frame.text)
            # 在新幻灯片中寻找相同类型的形状并填充文本
            for new_shape in new_slide.shapes:
                if new_shape.has_text_frame and hasattr(shape, 'placeholder_format'):
                    if new_shape.placeholder_format.idx == shape.placeholder_format.idx:
                        new_shape.text_frame.text = shape.text_frame.text
                        print(f"复制文本: {shape.text_frame.text} 到新的占位符")
    return new_slide


def generate():
    """
    生成ppt
    :return:
    """

    # print(generate_section_content(text, outline.strip()))
    from config.example import outline
    outline = json.loads(outline_to_json(outline))  # 大纲转为json后，按章节生成小节内容
    print(outline)
    chapters = outline['chapters']
    print(chapters)
    title = outline['title']

    # 加载ppt模板
    template_path = r"C:\研究生\研究生所学知识技术\实验室项目\智能出题\AI-PPT\template\test-template.pptx"

    prs = load_template(template_path)

    # 初始化 LayoutManager，使用配置文件中的 layout_mapping
    layout_mapping = get_layout_mapping(prs)
    print(layout_mapping)
    remove_all_slides(prs)  # 清除模板中所有幻灯片
    prs.core_properties.title = title  # 设置PowerPoint 的核心标题
    # 遍历所有幻灯片数据，生成对应的PPT
    # for layout in prs.slide_layouts:
    #     print(layout)
    # 模板的所有页数的名字
    keys = layout_mapping.keys()
    # for key in keys:
    #     print(key)
    # 随机匹配一个在layout_mapping中以title开头的布局
    title_layout_key = random.choice([key for key in keys if key.startswith("title")])
    title_layout_id = layout_mapping[title_layout_key]
    print(f"title_layout: {title_layout_key}, title_layout_id: {title_layout_id}")
    # 模板的特定布局
    title_layout = prs.slide_layouts[title_layout_id]  # ppt首页
    # 使用母版创建首页
    # 新PPT的布局
    new_slide = prs.slides.add_slide(title_layout)
    # 调用复制文本的函数
    new_slide = copy_placeholder_text_to_slide(title_layout, new_slide)
    # 对新幻灯片的文本进行替换
    for shape in new_slide.shapes:
        if shape.has_text_frame:
            text = shape.text_frame.text.strip()
            print("text:", text)
            # 替换内容
            if "标题" in text:
                print(f"替换标题：{title}")
                shape.text_frame.text = title
            elif "智能PPT" in text:
                print(f"替换智能PPT：{text}")
                shape.text_frame.text = "AI PPT"

    # 处理目录页
    # 随机匹配一个在layout_mapping中以content开头的布局
    content_layout_key = random.choice([key for key in keys if key.startswith("content")])
    content_layout_id = layout_mapping[content_layout_key]
    print(f"content_layout: {content_layout_key}, content_layout_id: {content_layout_id}")
    content_layout = prs.slide_layouts[content_layout_id]
    new_slide = prs.slides.add_slide(content_layout)
    new_slide = copy_placeholder_text_to_slide(content_layout, new_slide)
    for idx, chapter in enumerate(chapters):
        num = idx + 1
        chapter_title = chapter["chapter"]
        matched = False
        for shape in new_slide.shapes:
            if shape.has_text_frame:
                text = shape.text_frame.text.strip()
                if "目录" in text:
                    print(f"替换目录占位符")
                    shape.text_frame.text = "目录"
                if "content" in text:
                    print(f"替换content占位符")
                    shape.text_frame.text = "content"
                if f"序号{num}" in text:
                    print(f"替换序号：{num}")
                    shape.text_frame.text = f"{num}"
                if f"章节标题{num}" in text:
                    print(f"替换章节标题：{chapter_title}")
                    shape.text_frame.text = f"{chapter_title}"
                print("text:", text)
    # 清除未匹配的内容
    for shape in new_slide.shapes:
        if shape.has_text_frame:
            text = shape.text_frame.text.strip()
            if "序号" in text:
                print(f"清除序号占位符内容")
                shape.text_frame.text = ""
            if "章节标题" in text:
                print(f"清除章节标题占位符内容")
                shape.text_frame.text = ""

    ########################################################################
    # 处理章节页
    num = 0
    for chapter in chapters:
        # 处理章节页
        # 记录章节编码，从第一章开始为1
        num += 1
        chapter_layout_key = random.choice([key for key in keys if key.startswith("chapter")])
        chapter_layout_id = layout_mapping[chapter_layout_key]
        print(f"chapter_layout: {chapter_layout_key}, chapter_layout_id: {chapter_layout_id}")
        chapter_layout = prs.slide_layouts[chapter_layout_id]

        chapter_slide = prs.slides.add_slide(chapter_layout)
        new_slide = copy_placeholder_text_to_slide(chapter_layout, chapter_slide)
        # 替换内容
        # 对新幻灯片的文本进行替换
        for shape in new_slide.shapes:
            if shape.has_text_frame:
                text = shape.text_frame.text.strip()
                print("text:", text)
                # 替换内容
                if "章节序号" in text:
                    print(f"替换序号：0{num}")
                    shape.text_frame.text = f"0{num}"
                elif "章节标题" in text:
                    print(f"替换章节标题：{text}")
                    shape.text_frame.text = chapter["chapter"]
        # 根据章节md，生成小节内容
        chapter_md = chapter2md(chapter)
        section = generate_section_content(reference, chapter_md)
        print(section)
        chapter = json.loads(chapter2json(section))
        slides = chapter["slides"]
        # 根据slide内容生成幻灯片
        for slide in slides:  # 根据section的长度随机选择合适的母版
            sections = slide["sections"]
            num = len(sections)
            print(f"num: {num}")
            slide_layout_key = random.choice([key for key in keys if key.startswith(f"{num} section")])
            slide_layout_id = layout_mapping[slide_layout_key]
            print(f"slide_layout: {slide_layout_key}, slide_layout_id: {slide_layout_id}")
            content_layout = prs.slide_layouts[slide_layout_id]
            new_slide = prs.slides.add_slide(content_layout)
            new_slide = copy_placeholder_text_to_slide(content_layout, new_slide)
            for shape in new_slide.shapes:
                if shape.has_text_frame:
                    text = shape.text_frame.text.strip()
                    if "标题" in text:
                        shape.text_frame.text = slide["slide"]
                    i = 1
                    for item in sections:
                        # 替换内容
                        if f"小节标题{i}" in text:
                            print("替换小节标题")
                            shape.text_frame.text = item["section"]
                        if f"小节内容{i}" in text:
                            print("替换章节标题")
                            shape.text_frame.text = item["section_content"]
                        i += 1
    prs.save("modified_presentation.pptx")
    # print(chapter)
    # print(type(chapter))
    # chapter_md = chapter2md(chapter)
    # section = generate_section_content(text, chapter_md)

    # print("生成结果：")
    # print(section)

generate()
